package com.alibaba.citrus.ots.sales.plan.facade.service.salesplan.adjust;

import com.alibaba.citrus.ots.common.annotation.EpochTransactional;
import com.alibaba.citrus.ots.common.annotation.FacadeInvoker;
import com.alibaba.citrus.ots.common.exception.FacadeException;
import com.alibaba.citrus.ots.sales.plan.api.salesplan.adjust.SalesPlanAdjustWriteService;
import com.alibaba.citrus.ots.sales.plan.api.salesplan.audit.SalesPlanAdjustSendWxMessageService;
import com.alibaba.citrus.ots.sales.plan.dto.api.request.PageQueryPlanLineRequest;
import com.alibaba.citrus.ots.sales.plan.dto.api.request.PageQuerySalePlanRequest;
import com.alibaba.citrus.ots.sales.plan.dto.api.request.QuerySalesPlanRequest;
import com.alibaba.citrus.ots.sales.plan.facade.msg.SalesPlanAdjustSendMessageImpl;
import com.alibaba.citrus.ots.sales.plan.functions.salesplan.SalesPlanEntity;
import com.alibaba.citrus.ots.sales.plan.functions.salesplan.adjust.SalesPlanAdjustDetailAbility;
import com.alibaba.citrus.ots.sales.plan.model.SalesPlanLineStatusEnum;
import com.alibaba.citrus.ots.sales.plan.model.enums.SalesPlanCheckStatusEnum;
import com.alibaba.citrus.ots.sales.plan.model.enums.SalesPlanModelEnum;
import com.alibaba.citrus.ots.sales.plan.model.enums.SalesPlanStatusEnum;
import com.alibaba.citrus.ots.sales.plan.repository.SalesPlanLineRepository;
import com.alibaba.citrus.ots.sales.plan.repository.SalesPlanRepository;
import com.alibaba.citrus.ots.sales.plan.sdo.SalesPlanAdjustDetailSDO;
import com.alibaba.citrus.ots.sales.plan.sdo.SalesPlanLineSDO;
import com.alibaba.citrus.ots.sales.plan.sdo.SalesPlanSDO;
import com.alibaba.cz.base.tool.log.Log;
import com.alibaba.cz.base.tool.page.PageResult;
import com.alibaba.lattice2.epoch.sdk.model.Result;
import com.google.common.collect.Lists;
import org.apache.commons.collections.CollectionUtils;
import org.jetbrains.annotations.Nullable;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;

/**
 * @author yuhailin
 * @description:
 * @date 2021-10-25 15:49
 */
@Service
public class SalesPlanAdjustWriteServiceImpl implements SalesPlanAdjustWriteService {
    private final Log log = Log.getLogger(SalesPlanAdjustWriteServiceImpl.class);

    @Resource
    SalesPlanRepository salesPlanRepository;

    @Resource
    SalesPlanLineRepository salesPlanLineRepository;

    @Resource
    SalesPlanAdjustDetailAbility salesPlanAdjustDetailAbility;

    @Resource
    SalesPlanAdjustSendWxMessageService wxMessageService;

    /**
     * 计划明细page_size
     */
    private static final Integer SALES_PLAN_LIN_PAGE_SIZE = 500;


    @Override
    @FacadeInvoker
    @EpochTransactional(appCode = "bc_ots", dataSourceCode = "cr_ots", dataSourceType = "app")
    public Result<String> createSalesPlanAdjust(SalesPlanSDO salesPlanSDO) {
        //校验时间
        Result result = checkParameter(salesPlanSDO);
        if (result != null) return result;
        //校验计划是否存在正在调整中的数据
        checkIsAdjust(salesPlanSDO);
        QuerySalesPlanRequest querySalesPlanRequest = new QuerySalesPlanRequest();
        querySalesPlanRequest.setId(salesPlanSDO.getId().toString());
        SalesPlanSDO load = salesPlanRepository.load(querySalesPlanRequest);
        if (Objects.isNull(load)) {
            throw new FacadeException("OTS-02-002-00-16-001");
        }
        SalesPlanSDO sdo = new SalesPlanSDO();
        BeanUtils.copyProperties(load, sdo);
        sdo.setParentId(load.getId().intValue());
        sdo.setId(null);
        sdo.setCreator(null);
        sdo.setUpdater(null);
        sdo.setGmtCreate(null);
        sdo.setGmtModified(null);
        sdo.setCheckStatus(SalesPlanCheckStatusEnum.INIT_DRAFT.getCode());
        sdo.setModel(SalesPlanModelEnum.ADJUST_MODEL.getModel());
        sdo.setStatus(SalesPlanStatusEnum.ADJUST.getCode());
        sdo.setStartTime(salesPlanSDO.getStartTime());
        sdo.setEndTime(salesPlanSDO.getEndTime());
        sdo.setMonthFirst(salesPlanSDO.getMonthFirst());
        sdo.setMonthMiddle(salesPlanSDO.getMonthMiddle());
        sdo.setMonthLast(salesPlanSDO.getMonthLast());
        sdo.setPlanNotice(salesPlanSDO.getPlanNotice());
        // 构造实体
        SalesPlanEntity salesPlanEntity = SalesPlanEntity.of(sdo);
        String lastInsertId = salesPlanEntity.save();
        if (Integer.parseInt(lastInsertId) > 0) {
            //新增调整明细
            PageQueryPlanLineRequest queryPlanLineRequest = new PageQueryPlanLineRequest();
            queryPlanLineRequest.setPlanId(salesPlanSDO.getId().toString());
            queryPlanLineRequest.setStatus(SalesPlanLineStatusEnum.FINISH.getStatus());
            //获取总数
            PageResult<List<SalesPlanLineSDO>> listPageResult = salesPlanLineRepository.pageQuerySalesPlanLineList(queryPlanLineRequest);
            int totalPage = (listPageResult.getTotal() + SALES_PLAN_LIN_PAGE_SIZE - 1) / SALES_PLAN_LIN_PAGE_SIZE;
            //调整明细数据
            List<SalesPlanAdjustDetailSDO> salesPlanAdjustDetailSDOList = new ArrayList<>();
            for (int i = 1; i <= totalPage; i++) {
                queryPlanLineRequest.setSize(SALES_PLAN_LIN_PAGE_SIZE);
                queryPlanLineRequest.setPage(i);
                PageResult<List<SalesPlanLineSDO>> listPageResult2 = salesPlanLineRepository.pageQuerySalesPlanLineList(queryPlanLineRequest);
                if (CollectionUtils.isEmpty(listPageResult2.getContent())) {
                    break;
                }
                listPageResult2.getContent().stream().forEach(salesPlanLineSDO -> {
                    SalesPlanAdjustDetailSDO salesPlanAdjustDetailSDO = SalesPlanAdjustDetailSDO.builder().build();
                    BeanUtils.copyProperties(salesPlanLineSDO, salesPlanAdjustDetailSDO);
                    salesPlanAdjustDetailSDO.setAdjustId(Long.valueOf(lastInsertId));
                    salesPlanAdjustDetailSDO.setPlanDetailId(salesPlanLineSDO.getId());
                    salesPlanAdjustDetailSDO.setPlanId(salesPlanSDO.getId().toString());
                    salesPlanAdjustDetailSDO.setStatus(SalesPlanLineStatusEnum.FINISH.getStatus());
                    salesPlanAdjustDetailSDO.setId(null);
                    salesPlanAdjustDetailSDO.setCreator(null);
                    salesPlanAdjustDetailSDO.setUpdater(null);
                    salesPlanAdjustDetailSDO.setGmtCreate(null);
                    salesPlanAdjustDetailSDO.setGmtModified(null);
                    //调整量置0
                    salesPlanAdjustDetailSDO.setAdjustCount(0);
                    salesPlanAdjustDetailSDO.setMonthFirstAdjustCount(0);
                    salesPlanAdjustDetailSDO.setMonthMiddleAdjustCount(0);
                    salesPlanAdjustDetailSDO.setMonthLastAdjustCount(0);
                    salesPlanAdjustDetailSDO.setMonthFirstAdjustReturnCount(0);
                    salesPlanAdjustDetailSDO.setMonthMiddleAdjustReturnCount(0);
                    salesPlanAdjustDetailSDO.setMonthLastAdjustReturnCount(0);
                    salesPlanAdjustDetailSDO.setMonthFirstAdjustTotalCount(0);
                    salesPlanAdjustDetailSDO.setMonthMiddleAdjustTotalCount(0);
                    salesPlanAdjustDetailSDO.setMonthLastAdjustTotalCount(0);
                    salesPlanAdjustDetailSDO.setAdjustMoney(0l);
                    salesPlanAdjustDetailSDO.setBeforeAdjustMoney(0l);
                    salesPlanAdjustDetailSDOList.add(salesPlanAdjustDetailSDO);
                });
            }
            if (CollectionUtils.isEmpty(salesPlanAdjustDetailSDOList)) {
                throw new FacadeException("OTS-02-002-00-16-004");
            }
            String successCount = salesPlanAdjustDetailAbility.batchCreateSalesPlanAdjustDetail(salesPlanAdjustDetailSDOList);
            if (Integer.valueOf(successCount) > 0) {
                //修改月度计划状态
                SalesPlanSDO planSDO = new SalesPlanSDO();
                planSDO.setId(load.getId());
                planSDO.setStatus(SalesPlanStatusEnum.ADJUST.getCode());
                SalesPlanEntity salesPlanEntity2 = SalesPlanEntity.of(planSDO);
                salesPlanEntity2.updateSalesPlanStatus();

                //0413需求，调整时发送微信小程序通知，发送失败也不阻断流程，打印错误日志
                try {
                    log.info("Start_sendWxSubscribeMessage:{}", load.getId());
                    wxMessageService.sendWxSubscribeMessage(String.valueOf(load.getId()));
                }catch (Exception e){
                    log.error("SendAdjustWxMessage_Failed:{}",load.getId());
                }
            }
            return Result.success(lastInsertId);
        }
        return null;
    }

    @Nullable
    private Result checkParameter(SalesPlanSDO salesPlanSDO) {
        //开始结束时间不能为空
        if (null == salesPlanSDO.getStartTime() || null == salesPlanSDO.getEndTime()) {
            Result result = new Result();
            result.setSuccess(false);
            Map<String, Object> validateErrors = new HashMap<>();
            validateErrors.put("adjustTime", "调整起止时间 是必填字段");
            result.setValidateErrors(validateErrors);
            return result;
        }

        //提报开始时间不能小于当前时间
        if (null != salesPlanSDO.getStartTime()) {
            //当前时间
            Date currentTime = new Date();
            Date startTime = salesPlanSDO.getStartTime();
            int compareTo = startTime.compareTo(currentTime);
            if (compareTo < 0) {
                Result result = new Result();
                result.setSuccess(false);
                Map<String, Object> validateErrors = new HashMap<>();
                validateErrors.put("adjustTime", "调整开始时间应在当前时间之后");
                result.setValidateErrors(validateErrors);
                return result;
            }
        }


        //提报结束不能小于当前时间
        if (null != salesPlanSDO.getEndTime()) {
            //当前时间
            Date currentTime = new Date();
            Date endTime = salesPlanSDO.getEndTime();
            int compareTo = endTime.compareTo(currentTime);
            if (compareTo < 0) {
                Result result = new Result();
                result.setSuccess(false);
                Map<String, Object> validateErrors = new HashMap<>();
                validateErrors.put("adjustTime", "调整开始时间应在当前时间之后");
                result.setValidateErrors(validateErrors);
                return result;
            }
        }

        //提报结束时间不能大于提报开始时间
        if (null != salesPlanSDO.getStartTime() && null != salesPlanSDO.getEndTime()) {
            Date startTime = salesPlanSDO.getStartTime();
            Date endTime = salesPlanSDO.getEndTime();
            int compareTo = endTime.compareTo(startTime);
            if (compareTo < 0) {
                Result result = new Result();
                result.setSuccess(false);
                Map<String, Object> validateErrors = new HashMap<>();
                validateErrors.put("adjustTime", "调整结束时间应在调整开始时间之后");
                result.setValidateErrors(validateErrors);
                return result;
            }
        }
        return null;
    }

    private void checkIsAdjust(SalesPlanSDO salesPlanSDO) {
        PageQuerySalePlanRequest pageQuerySalePlanRequest = new PageQuerySalePlanRequest();
        pageQuerySalePlanRequest.setParentId(salesPlanSDO.getId().toString());
        pageQuerySalePlanRequest.setModel(SalesPlanModelEnum.ADJUST_MODEL.getModel());
//        pageQuerySalePlanRequest.setStatus(SalesPlanStatusEnum.ADJUST.getCode().toString());
        pageQuerySalePlanRequest.setStatusList(Lists.newArrayList(SalesPlanStatusEnum.ADJUST.getCode(), SalesPlanStatusEnum.ADJUSTED_TO_BE_REPLIED.getCode(), SalesPlanStatusEnum.ADJUSTED_TO_BE_PUBLISHED.getCode()));
        PageResult<List<SalesPlanSDO>> listPageResult1 = salesPlanRepository.pageQuery(pageQuerySalePlanRequest);
        if (listPageResult1.getContent().size() > 0) {
            throw new FacadeException("OTS-02-005-00-15-015");
        }
    }
}
